package logger

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"time"
)

// AWSConfig AWS部署配置
type AWSConfig struct {
	Regions []string `json:"regions"`
	InstanceTypes map[string]string `json:"instance_types"`
	AMIs map[string]string `json:"ami_ids"`
	SecurityGroups map[string]string `json:"security_groups"`
	KeyPairs map[string]string `json:"key_pairs"`
}

// BenchmarkConfig 基准测试配置
type BenchmarkConfig struct {
	DefaultSettings struct {
		Nodes     int `json:"nodes"`
		Duration  int `json:"duration"`
		BatchSize int `json:"batch_size"`
	} `json:"default_settings"`
	
	TestScenarios []struct {
		Name         string `json:"name"`
		Nodes        int    `json:"nodes"`
		InstanceType string `json:"instance_type"`
		Duration     int    `json:"duration"`
	} `json:"test_scenarios"`
}

// MonitoringConfig 监控配置
type MonitoringConfig struct {
	CollectMetrics bool `json:"collect_metrics"`
	MetricsInterval int `json:"metrics_interval"`
	LogLevel int `json:"log_level"`
}

// DeploymentConfig 完整部署配置
type DeploymentConfig struct {
	AWS       AWSConfig       `json:"aws"`
	Benchmark BenchmarkConfig `json:"benchmark"`
	Monitoring MonitoringConfig `json:"monitoring"`
}

// AWSDeployer AWS部署器
type AWSDeployer struct {
	config *DeploymentConfig
	logDir string
}

// NewAWSDeployer 创建AWS部署器
func NewAWSDeployer(configPath string, logDir string) (*AWSDeployer, error) {
	config, err := loadConfig(configPath)
	if err != nil {
		return nil, err
	}

	return &AWSDeployer{
		config: config,
		logDir: logDir,
	}, nil
}

// loadConfig 加载配置文件
func loadConfig(configPath string) (*DeploymentConfig, error) {
	file, err := os.Open(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to open config file: %v", err)
	}
	defer file.Close()

	var config DeploymentConfig
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&config); err != nil {
		return nil, fmt.Errorf("failed to decode config: %v", err)
	}

	return &config, nil
}

// GenerateDeploymentScript 生成部署脚本
func (ad *AWSDeployer) GenerateDeploymentScript(scenario string) error {
	// 查找测试场景
	var selectedScenario *struct {
		Name         string `json:"name"`
		Nodes        int    `json:"nodes"`
		InstanceType string `json:"instance_type"`
		Duration     int    `json:"duration"`
	}

	for _, s := range ad.config.Benchmark.TestScenarios {
		if s.Name == scenario {
			selectedScenario = &s
			break
		}
	}

	if selectedScenario == nil {
		return fmt.Errorf("scenario '%s' not found", scenario)
	}

	// 生成部署脚本
	script := fmt.Sprintf(`#!/bin/bash
# EbbFlow AWS Deployment Script
# Generated at: %s
# Scenario: %s

set -e

# Configuration
NODES=%d
INSTANCE_TYPE=%s
DURATION=%d
REGION=%s

echo "Starting EbbFlow AWS deployment..."
echo "Nodes: $NODES"
echo "Instance Type: $INSTANCE_TYPE"
echo "Duration: $DURATION seconds"
echo "Region: $REGION"

# Create instances
echo "Creating AWS instances..."
for i in $(seq 0 $((NODES-1))); do
    echo "Creating node $i..."
    aws ec2 run-instances \\
        --image-id %s \\
        --instance-type $INSTANCE_TYPE \\
        --key-name %s \\
        --security-group-ids %s \\
        --region $REGION \\
        --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ebbflow-node-$i}]' \\
        --user-data file://user_data.sh
done

# Wait for instances to be ready
echo "Waiting for instances to be ready..."
sleep 60

# Get instance IPs
echo "Getting instance IPs..."
aws ec2 describe-instances \\
    --filters "Name=tag:Name,Values=ebbflow-node-*" \\
		--query 'Reservations[*].Instances[*].[PublicIpAddress,Tags[?Key==Name].Value|[0]]' \\
    --output table

echo "Deployment completed!"
`,
		time.Now().Format("2006-01-02 15:04:05"),
		scenario,
		selectedScenario.Nodes,
		selectedScenario.InstanceType,
		selectedScenario.Duration,
		ad.config.AWS.Regions[0],
		ad.config.AWS.AMIs[ad.config.AWS.Regions[0]],
		ad.config.AWS.KeyPairs[ad.config.AWS.Regions[0]],
		ad.config.AWS.SecurityGroups[ad.config.AWS.Regions[0]])

	// 写入脚本文件
	scriptPath := filepath.Join(ad.logDir, "deploy_aws.sh")
	if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
		return fmt.Errorf("failed to write deployment script: %v", err)
	}

	// 生成用户数据脚本
	userData := `#!/bin/bash
# EbbFlow Node Setup Script

# Update system
yum update -y

# Install Go
curl -O https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile

# Install dependencies
yum install -y git make gcc

# Clone and build EbbFlow
cd /home/ec2-user
git clone <EBBFLOW_REPO_URL> ebbflow
cd ebbflow
make

# Start EbbFlow server
./bin/ebbflow_server $NODE_ID &
`

	userDataPath := filepath.Join(ad.logDir, "user_data.sh")
	if err := os.WriteFile(userDataPath, []byte(userData), 0644); err != nil {
		return fmt.Errorf("failed to write user data script: %v", err)
	}

	fmt.Printf("Deployment script generated: %s\n", scriptPath)
	fmt.Printf("User data script generated: %s\n", userDataPath)
	
	return nil
}

// GenerateTestScript 生成测试脚本
func (ad *AWSDeployer) GenerateTestScript(scenario string) error {
	script := fmt.Sprintf(`#!/bin/bash
# EbbFlow AWS Test Script
# Generated at: %s

set -e

echo "Starting EbbFlow AWS test..."

# Get instance IPs
IPS=$(aws ec2 describe-instances \\
    --filters "Name=tag:Name,Values=ebbflow-node-*" \\
    --query 'Reservations[*].Instances[*].PublicIpAddress' \\
    --output text)

echo "Instance IPs: $IPS"

# Start servers on all nodes
for ip in $IPS; do
    echo "Starting server on $ip..."
    ssh -i ~/.ssh/ebbflow-key.pem ec2-user@$ip "cd ebbflow && ./bin/ebbflow_server 0 &"
done

# Wait for servers to start
sleep 10

# Start client on first node
FIRST_IP=$(echo $IPS | awk '{print $1}')
echo "Starting client on $FIRST_IP..."
ssh -i ~/.ssh/ebbflow-key.pem ec2-user@$FIRST_IP "cd ebbflow && ./bin/ebbflow_client 100 1 1000 test 1 &"

# Monitor performance
echo "Monitoring performance for 60 seconds..."
sleep 60

# Collect logs
echo "Collecting logs..."
mkdir -p logs
for ip in $IPS; do
    echo "Collecting logs from $ip..."
    scp -i ~/.ssh/ebbflow-key.pem ec2-user@$ip:ebbflow/logger/*.log logs/
done

echo "Test completed!"
`,
		time.Now().Format("2006-01-02 15:04:05"))

	scriptPath := filepath.Join(ad.logDir, "test_aws.sh")
	if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
		return fmt.Errorf("failed to write test script: %v", err)
	}

	fmt.Printf("Test script generated: %s\n", scriptPath)
	return nil
}

// CreateConfigFile 创建配置文件
func (ad *AWSDeployer) CreateConfigFile() error {
	configPath := filepath.Join(ad.logDir, "aws_config.yaml")
	
	config := `aws:
  regions:
    - us-east-1
    - us-west-2
    - eu-west-1
  
  instance_types:
    small: t3.medium
    medium: t3.large
    large: t3.xlarge
    xlarge: t3.2xlarge
  
  ami_ids:
    us-east-1: ami-0c02fb55956c7d316  # Amazon Linux 2
    us-west-2: ami-0c02fb55956c7d316
    eu-west-1: ami-0c02fb55956c7d316
  
  security_groups:
    us-east-1: sg-12345678
    us-west-2: sg-87654321
    eu-west-1: sg-11223344
  
  key_pairs:
    us-east-1: ebbflow-aws-key
    us-west-2: ebbflow-aws-key
    eu-west-1: ebbflow-aws-key

benchmark:
  default_settings:
    nodes: 4
    duration: 60
    batch_size: 100
  
  test_scenarios:
    - name: "small_cluster"
      nodes: 4
      instance_type: t3.medium
      duration: 30
    
    - name: "medium_cluster"
      nodes: 7
      instance_type: t3.large
      duration: 60
    
    - name: "large_cluster"
      nodes: 16
      instance_type: t3.xlarge
      duration: 120
    
    - name: "stress_test"
      nodes: 32
      instance_type: t3.2xlarge
      duration: 300

monitoring:
  collect_metrics: true
  metrics_interval: 10
  log_level: 1`

	if err := os.WriteFile(configPath, []byte(config), 0644); err != nil {
		return fmt.Errorf("failed to write config file: %v", err)
	}

	fmt.Printf("Config file created: %s\n", configPath)
	return nil
}
